package utilService

import (
	"beesoft.ink/application/media/app/helper/media/font"
	"context"
	"fmt"
	"io"
	"unicode/utf8"
)

func NewPdf(ctx context.Context, fontPathPrefix string) *Pdf {
	pdf := gofpdf.New("P", "mm", "A4", "")
	pdf.SetMargins(20, 20, 20)
	pdf.SetAutoPageBreak(false, 20)

	r := &Pdf{
		ctx:            ctx,
		pdf:            pdf,
		fontPathPrefix: fontPathPrefix,
	}

	r.AddFonts([]string{
		"arial",
		"times",
		"simsun",         // 中文 宋体
		"yugothic",       // 日语
		"msyh",           // 中文 微软雅黑
		"NotoColorEmoji", // 表情
	})

	r.pdf.AddPage()

	return r
}

type Pdf struct {
	ctx            context.Context
	pdf            *gofpdf.Fpdf
	fontPathPrefix string
}

func (r *Pdf) Pdf() *gofpdf.Fpdf {
	return r.pdf
}

func (r *Pdf) FontPath(fontFamily string) string {
	return fmt.Sprintf("%s/%s.ttf", r.fontPathPrefix, fontFamily)
}
func (r *Pdf) AddFont(fontFamily string) *Pdf {
	r.pdf.AddUTF8Font(fontFamily, "", r.FontPath(fontFamily))

	return r
}
func (r *Pdf) AddFonts(fontFamilies []string) *Pdf {
	for _, fontFamily := range fontFamilies {
		r.AddFont(fontFamily)
	}

	return r
}
func (r *Pdf) SetFontAndOutput(fontName string, size float64, text string) {
	r.pdf.SetFont(fontName, "", size)
	r.pdf.CellFormat(float64(utf8.RuneLen([]rune(text)[0])), 10, text, "", 0, "", false, 0, "")
}

func (r *Pdf) MultiCell(content string) *Pdf {
	fonts := map[string]*font.Font{
		"arial":    font.NewFont(r.ctx, r.FontPath("arial")),
		"times":    font.NewFont(r.ctx, r.FontPath("times")),
		"simsun":   font.NewFont(r.ctx, r.FontPath("simsun")),
		"yugothic": font.NewFont(r.ctx, r.FontPath("yugothic")),
		"msyh":     font.NewFont(r.ctx, r.FontPath("msyh")),
		// "NotoColorEmoji": NewFont(r.ctx, r.FontPath("NotoColorEmoji")),
	}
	// A4 210×297mm
	var (
		minWidth   float64 = 20
		maxWidth   float64 = 190
		minHeight  float64 = 20
		maxHeight  float64 = 277
		lineHeight float64 = 8
	)

	for _, char := range content {
		if string(char) == "\n" {
			_, startY := r.pdf.GetXY() // 获取位置
			y := startY + lineHeight
			if y > maxHeight {
				r.pdf.AddPage()
				y = minHeight
			}
			r.pdf.SetXY(minWidth, y)
			continue
		}
		for fontName, font := range fonts {
			if font.Exists(char) {
				r.pdf.SetFont(fontName, "", 12) // 设置字体
				startX, startY := r.pdf.GetXY() // 获取位置

				r.pdf.MultiCell(0, 6, string(char), "", "", false) // 设置文字

				x := startX + r.pdf.GetStringWidth(string(char))
				y := startY
				if x >= maxWidth {
					x = minWidth
					y = startY + lineHeight
				}
				if y > maxHeight {
					r.pdf.AddPage()
					y = minHeight
				}

				r.pdf.SetXY(x, y)
				break
			}
		}
	}

	return r
}
func (r *Pdf) MultiCellRaw(content string) *Pdf {
	r.pdf.MultiCell(0, 6, content, "", "", false)

	return r
}

func (r *Pdf) OutputAndClose(wc io.WriteCloser) error {
	return r.pdf.OutputAndClose(wc)
}
